# -*- coding: utf-8 -*-

################################################################################
## Form generated from reading UI file 'SYSTEM_PYSIDE6_TABLE_VIEWER_1_0baKiPS.ui'
##
## Created by: Qt User Interface Compiler version 6.9.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
    QFont, QFontDatabase, QGradient, QIcon,
    QImage, QKeySequence, QLinearGradient, QPainter,
    QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QDialog, QFrame, QGroupBox,
    QHeaderView, QLabel, QLineEdit, QPushButton,
    QSizePolicy, QTabWidget, QTableView, QWidget)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        if not Dialog.objectName():
            Dialog.setObjectName(u"Dialog")
        Dialog.resize(851, 601)
        self.groupBox_1 = QGroupBox(Dialog)
        self.groupBox_1.setObjectName(u"groupBox_1")
        self.groupBox_1.setGeometry(QRect(0, 10, 841, 571))
        self.tableView_1 = QTableView(self.groupBox_1)
        self.tableView_1.setObjectName(u"tableView_1")
        self.tableView_1.setGeometry(QRect(20, 150, 801, 401))
        self.tabWidget_1 = QTabWidget(self.groupBox_1)
        self.tabWidget_1.setObjectName(u"tabWidget_1")
        self.tabWidget_1.setGeometry(QRect(20, 30, 801, 111))
        self.tabWidget_1.setDocumentMode(True)
        self.tab_1 = QWidget()
        self.tab_1.setObjectName(u"tab_1")
        self.pushButton_7 = QPushButton(self.tab_1)
        self.pushButton_7.setObjectName(u"pushButton_7")
        self.pushButton_7.setGeometry(QRect(580, 50, 211, 31))
        self.label_3 = QLabel(self.tab_1)
        self.label_3.setObjectName(u"label_3")
        self.label_3.setGeometry(QRect(10, 10, 101, 31))
        self.label_3.setFrameShape(QFrame.Shape.Box)
        self.label_3.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.pushButton_6 = QPushButton(self.tab_1)
        self.pushButton_6.setObjectName(u"pushButton_6")
        self.pushButton_6.setGeometry(QRect(690, 10, 101, 31))
        self.label_4 = QLabel(self.tab_1)
        self.label_4.setObjectName(u"label_4")
        self.label_4.setGeometry(QRect(10, 50, 101, 31))
        self.label_4.setFrameShape(QFrame.Shape.Box)
        self.label_4.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.pushButton_1 = QPushButton(self.tab_1)
        self.pushButton_1.setObjectName(u"pushButton_1")
        self.pushButton_1.setGeometry(QRect(580, 10, 101, 31))
        self.lineEdit_1 = QLineEdit(self.tab_1)
        self.lineEdit_1.setObjectName(u"lineEdit_1")
        self.lineEdit_1.setGeometry(QRect(120, 10, 451, 31))
        font = QFont()
        font.setFamilies([u"SimHei"])
        self.lineEdit_1.setFont(font)
        self.lineEdit_4 = QLineEdit(self.tab_1)
        self.lineEdit_4.setObjectName(u"lineEdit_4")
        self.lineEdit_4.setGeometry(QRect(120, 50, 451, 31))
        self.lineEdit_4.setFont(font)
        self.tabWidget_1.addTab(self.tab_1, "")
        self.tab_2 = QWidget()
        self.tab_2.setObjectName(u"tab_2")
        self.pushButton_5 = QPushButton(self.tab_2)
        self.pushButton_5.setObjectName(u"pushButton_5")
        self.pushButton_5.setGeometry(QRect(690, 50, 101, 31))
        self.pushButton_2 = QPushButton(self.tab_2)
        self.pushButton_2.setObjectName(u"pushButton_2")
        self.pushButton_2.setGeometry(QRect(580, 10, 101, 31))
        self.lineEdit_3 = QLineEdit(self.tab_2)
        self.lineEdit_3.setObjectName(u"lineEdit_3")
        self.lineEdit_3.setGeometry(QRect(120, 50, 451, 31))
        self.lineEdit_3.setFont(font)
        self.label_1 = QLabel(self.tab_2)
        self.label_1.setObjectName(u"label_1")
        self.label_1.setGeometry(QRect(10, 10, 101, 31))
        self.label_1.setFrameShape(QFrame.Shape.Box)
        self.label_1.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.pushButton_3 = QPushButton(self.tab_2)
        self.pushButton_3.setObjectName(u"pushButton_3")
        self.pushButton_3.setGeometry(QRect(580, 50, 101, 31))
        self.label_2 = QLabel(self.tab_2)
        self.label_2.setObjectName(u"label_2")
        self.label_2.setGeometry(QRect(10, 50, 101, 31))
        self.label_2.setFrameShape(QFrame.Shape.Box)
        self.label_2.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.pushButton_4 = QPushButton(self.tab_2)
        self.pushButton_4.setObjectName(u"pushButton_4")
        self.pushButton_4.setGeometry(QRect(690, 10, 101, 31))
        self.lineEdit_2 = QLineEdit(self.tab_2)
        self.lineEdit_2.setObjectName(u"lineEdit_2")
        self.lineEdit_2.setGeometry(QRect(120, 10, 451, 31))
        self.lineEdit_2.setFont(font)
        self.tabWidget_1.addTab(self.tab_2, "")
        self.tab_3 = QWidget()
        self.tab_3.setObjectName(u"tab_3")
        self.pushButton_8 = QPushButton(self.tab_3)
        self.pushButton_8.setObjectName(u"pushButton_8")
        self.pushButton_8.setGeometry(QRect(580, 10, 211, 31))
        self.label_5 = QLabel(self.tab_3)
        self.label_5.setObjectName(u"label_5")
        self.label_5.setGeometry(QRect(10, 10, 101, 31))
        self.label_5.setFrameShape(QFrame.Shape.Box)
        self.label_5.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.lineEdit_5 = QLineEdit(self.tab_3)
        self.lineEdit_5.setObjectName(u"lineEdit_5")
        self.lineEdit_5.setGeometry(QRect(120, 10, 451, 31))
        self.lineEdit_5.setFont(font)
        self.tabWidget_1.addTab(self.tab_3, "")

        self.retranslateUi(Dialog)

        self.tabWidget_1.setCurrentIndex(0)


        QMetaObject.connectSlotsByName(Dialog)
    # setupUi

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QCoreApplication.translate("Dialog", u"Dialog", None))
        self.groupBox_1.setTitle(QCoreApplication.translate("Dialog", u"GroupBox", None))
        self.pushButton_7.setText(QCoreApplication.translate("Dialog", u"Rename", None))
        self.label_3.setText(QCoreApplication.translate("Dialog", u"Data Source", None))
        self.pushButton_6.setText(QCoreApplication.translate("Dialog", u"Confirm", None))
        self.label_4.setText(QCoreApplication.translate("Dialog", u"Rename Cols", None))
        self.pushButton_1.setText(QCoreApplication.translate("Dialog", u"...", None))
        self.lineEdit_1.setPlaceholderText(QCoreApplication.translate("Dialog", u"C:\\Example.csv", None))
        self.lineEdit_4.setText(QCoreApplication.translate("Dialog", u"{\"Old_Name\": \"New_Name\"}", None))
        self.tabWidget_1.setTabText(self.tabWidget_1.indexOf(self.tab_1), QCoreApplication.translate("Dialog", u"Data Source", None))
        self.pushButton_5.setText(QCoreApplication.translate("Dialog", u"\u79fb\u9664\u5217", None))
        self.pushButton_2.setText(QCoreApplication.translate("Dialog", u"Filter", None))
        self.lineEdit_3.setText(QCoreApplication.translate("Dialog", u"{\"Only\": [  ], \"Exclude\": [  ]}", None))
        self.label_1.setText(QCoreApplication.translate("Dialog", u"Filter Rows", None))
        self.pushButton_3.setText(QCoreApplication.translate("Dialog", u"Filter", None))
        self.label_2.setText(QCoreApplication.translate("Dialog", u"Filter Cols", None))
        self.pushButton_4.setText(QCoreApplication.translate("Dialog", u"\u79fb\u9664\u884c", None))
        self.lineEdit_2.setText(QCoreApplication.translate("Dialog", u"{\"Only\": [  ], \"Exclude\": [  ]}", None))
        self.tabWidget_1.setTabText(self.tabWidget_1.indexOf(self.tab_2), QCoreApplication.translate("Dialog", u"Filter Rows and Cols", None))
        self.pushButton_8.setText(QCoreApplication.translate("Dialog", u"Query", None))
        self.label_5.setText(QCoreApplication.translate("Dialog", u"Pandas Query", None))
        self.lineEdit_5.setText(QCoreApplication.translate("Dialog", u"((index == index) & (index == index)) | (index == index)", None))
        self.tabWidget_1.setTabText(self.tabWidget_1.indexOf(self.tab_3), QCoreApplication.translate("Dialog", u"Pandas Query", None))
    # retranslateUi

# #############################################################################################
# 新增 PyQt / PySide 对话框类 Class (继承自 QDialog) 以使用 Qt Designer / PySide 生成的 UI 代码
# #############################################################################################

import json
import os
import sys
# ..................................................
import pandas
# ..................................................
from PySide6.QtCore import Qt                             # 用于处理键盘按键事件
from PySide6.QtGui  import QStandardItem, QIcon, QPixmap  # 用于对标准形式列表项配置细节
from PySide6.QtGui  import QStandardItemModel             # 用于生成标准形式列表

class Dialog_System_Table_Viewer(QDialog):

    # PyQt / PySide 对话框类 Class (继承自 QDialog)

    def __init__(self, parent = None):

        super().__init__(parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

        self.JSON_Records:list = [
            {"姓名": "张三", "年龄": "25", "职业": "工程师"},
            {"姓名": "李四", "年龄": "30", "职业": "设计师"},
            {"姓名": "王五", "年龄": "28", "职业": "产品经理"},
            {"姓名": "赵六", "年龄": "35", "职业": "总监"}
        ]

        # 初始显示样例数据
        self.for_tableViewer_1_setModel()

        # 连接信号和槽
        self.Setup_Connections()

    def Setup_Connections(self):

        """ 连接所有信号和槽 """

        # 连接按钮
        self.ui.pushButton_6.clicked.connect(self.on_pushButton_6_clicked)  # "确认 (Confirm)" 按键
        self.ui.pushButton_7.clicked.connect(self.on_pushButton_7_clicked)  # "重命名 (Rename)" 按键
        self.ui.pushButton_2.clicked.connect(self.on_pushButton_2_clicked)  # "筛选 (Filter)" 按键
        self.ui.pushButton_8.clicked.connect(self.on_pushButton_8_clicked)  # "查询 (Query)" 按键

    def keyPressEvent(self, event):
  
        """ 处理键盘按下事件 """
  
        key      = event.key()
        modifier = event.modifiers() # 判断修饰键
        # ..........................................
        # 处理特定按键
        if (key == Qt.Key.Key_Escape   ): self.close()  # 关闭窗口 (Esc)
        if (key == Qt.Key.Key_Backspace): self.on_pushButton_6_clicked()
        # ..........................................
        # 处理组合按键
        if (modifier == Qt.KeyboardModifier.ControlModifier):
            if (key == Qt.Key.Key_R): self.on_pushButton_6_clicked()  # Ctrl + R (Enter is Enter or Return)
        # ..........................................
        # 让文本编辑器正常处理文本输入 (其他按键交给父类处理)
        super().keyPressEvent(event)

    def DIY_JSON_Records_Get_Record_of_Longest(self, JSON_Records:list) -> dict:

        Record_of_Longest:list = {}
        # ..........................................
        Got_Length:int = 0
        # ..........................................
        for Record in JSON_Records:
            Record_Keys_Len = len(Record.keys())
            if (Record_Keys_Len > Got_Length):
                Got_Length = Record_Keys_Len
                Record_of_Longest = Record
        # ..........................................
        return Record_of_Longest

    def DIY_JSON_Records_Rename_Keys(self, JSON_Records:list, Mapping:dict) -> list:

        # Params:
        # - Mapping : dict -- Example: {"Old_Name": "New_Name", ..., "A": "B"}

        New_JSON_Records:list = []
        # ..........................................
        for Record in JSON_Records:
            New_Record:dict = {}
            # ......................................
            for Old_Key in Record.keys():
                for Map_Key in Mapping.keys():
                    if (Old_Key == Map_Key):
                        New_Key             = Mapping[Map_Key]
                        New_Record[New_Key] = Record[Old_Key]
                    else:
                        New_Record[Old_Key] = Record[Old_Key]
            # ......................................
            New_JSON_Records.append(New_Record)
        # ..........................................
        return New_JSON_Records

    def DIY_JSON_Records_Filter_Records(self, JSON_Records:dict, Filtering:dict) -> list:

        # Params:
        # - Filtering : dict -- Example: {"Only": [0, 2, ..., 6], "Exclude": [1, 3, ..., 5]}

        Selected_JSON_Records:list = []  # 选出的 (对应 Only)
        Excluded_JSON_Records:list = []  # 排除的 (对应 Exclude)
        Ultimate_JSON_Records:list = JSON_Records
        # ..........................................
        Count_Rows = len(JSON_Records)
        # ..........................................
        if (Filtering["Only"] != []):
            for RowIdx in range(0, Count_Rows, 1):
                if (RowIdx in Filtering["Only"]):
                    Selected_JSON_Records.append(JSON_Records[RowIdx])
            Ultimate_JSON_Records = Selected_JSON_Records
        # ..........................................
        if (Filtering["Exclude"] != []):
            for RowIdx in range(0, Count_Rows, 1):
                if (RowIdx in Filtering["Exclude"]):
                    Excluded_JSON_Records.append(JSON_Records[RowIdx])
            Ultimate_JSON_Records = list(
                filter(lambda x: x not in Excluded_JSON_Records, Ultimate_JSON_Records)
            )
        # ..........................................
        return Ultimate_JSON_Records

    def DIY_JSON_Records_Use_Pandas_Query(self, JSON_Records:list, Query:str) -> list:

        # Params:
        # - Query : str -- Example: "((A >= 20) & (B > 0)) | (A > C)"

        df = pandas.DataFrame(data = JSON_Records, dtype = str)
        # ..........................................
        df = df.query(Query)
        # ..........................................
        New_JSON_Records = df.to_dict(orient = "records")
        # ..........................................
        return New_JSON_Records

    def DIY_Read_CSV_to_JSON_Records(self, CSV_Path:str,
                                           Encoding:str = "utf-8",
                                           Headers_Row:int = 0) -> list:
    
        CSV_File  = open(CSV_Path, mode = 'r', encoding = Encoding)
        CSV_Lines = CSV_File.readlines()
        CSV_File.close()
        # ..........................................
        List2D:list = []
        # ..........................................
        for Line in CSV_Lines:
            Ln  = Line.replace('\n', '')  # 清除每 1 行末尾的换行符 "\n"
            Lst = Ln.split(',')
            List2D.append(Lst)
        # ..........................................
        Headers:list = []  # be Similar to: ["姓名", "年龄", "职业"]
        # ..........................................
        for ColIdx in range(0, len(List2D[Headers_Row]), 1):
            Headers.append(List2D[Headers_Row][ColIdx])
        # ..........................................
        JSON_Records:list = []
        # ..........................................
        for RowIdx in range(Headers_Row + 1, len(List2D), 1):
            Line:dict = {}  # be Similar to: {"姓名": "张三", "年龄": "25", "职业": "工程师"}
            for ColIdx in range(0, len(List2D[RowIdx]), 1):
                Key       = Headers[ColIdx]
                Val       = List2D[RowIdx][ColIdx]
                Line[Key] = Val
            JSON_Records.append(Line)
        # ..........................................
        return JSON_Records

    def for_tableViewer_1_setModel(self):

        Record_of_Longest = self.DIY_JSON_Records_Get_Record_of_Longest(self.JSON_Records)
        # ..........................................
        Count_Rows = len(self.JSON_Records)  # 获取行数
        Count_Cols = len(Record_of_Longest.keys())  # 获取列数
        # ..........................................
        # 创建数据模型
        # >>> # 创建 "2 行 2 列" 的数据模型
        # >>> model = QStandardItemModel(2, 2)
        # >>> # 设置数据模型的横向标签
        # >>> model.setHorizontalHeaderLabels(["姓名", "年龄"])
        # >>> # 设置数据模型的数据
        # >>> model.setItem(0, 0, QStandardItem("张三"))
        # >>> model.setItem(0, 1, QStandardItem("25"))
        # >>> model.setItem(1, 0, QStandardItem("李四"))
        # >>> model.setItem(1, 1, QStandardItem("30"))
        # >>> Ui_Dialog().tableView_1.setModel(model)  # 为视图装载模型
        # Qt6 中 QTableViewer 显示示例:
        #    姓名  年龄
        # 1  张三    25
        # 2  李四    30
        # >>> # 自定义数据模型竖向标签
        # >>> RowIdxItem = QStandardItem("Y01")
        # >>> RowIdxItem.setTextAlignment(Qt.AlignCenter)          # 居中对齐
        # >>> RowIdxItem.setFont(QFont("Arial", 10, QFont.Bold))   # 设置字体
        # >>> RowIdxItem.setForeground(QBrush(QColor(255, 0, 0)))  # 设置文字颜色为红色
        # >>> model.setVerticalHeaderItem(0, RowIdxItem)
        # >>> RowIdxItem = QStandardItem("Y02")
        # >>> model.setVerticalHeaderItem(1, RowIdxItem)
        # >>> Ui_Dialog().tableView_1.setModel(model)  # 为视图装载模型
        # >>> # 自定义数据模型竖向标签的行高
        # >>> Ui_Dialog().tableView_1.verticalHeader().setDefaultSectionSize(40)
        # Qt6 中 QTableViewer 显示示例:
        #      姓名  年龄
        # Y01  张三    25
        # Y02  李四    30
        # ..........................................
        model = QStandardItemModel(Count_Rows, Count_Cols)
        model.setHorizontalHeaderLabels(Record_of_Longest.keys())
        # ..........................................
        for RowIdx in range(0, Count_Rows, 1):
            Record_Keys = list(self.JSON_Records[RowIdx].keys())
            Count_Keys  = len(Record_Keys)
            # ......................................
            for ColIdx in range(0, Count_Keys, 1):
                Key   = Record_Keys[ColIdx]
                Value = self.JSON_Records[RowIdx][Key]
                Item  = QStandardItem(Value)
                model.setItem(RowIdx, ColIdx, Item)
            # ......................................
            # 自定义数据模型竖向标签
            model.setVerticalHeaderItem(RowIdx, QStandardItem(str(RowIdx)))
        # ..........................................
        # 为视图装载模型
        self.ui.tableView_1.setModel(model)

    def on_pushButton_6_clicked(self):

        Inputed:str = self.ui.lineEdit_1.text()
        # ..........................................
        if (Inputed != ''):
            self.JSON_Records = self.DIY_Read_CSV_to_JSON_Records(CSV_Path = Inputed)
            self.for_tableViewer_1_setModel()

    def on_pushButton_7_clicked(self):

        Inputed:str  = self.ui.lineEdit_4.text()
        Mapping:dict = json.loads(Inputed)
        # ..........................................
        self.JSON_Records = self.DIY_JSON_Records_Rename_Keys(self.JSON_Records, Mapping)
        # ..........................................
        self.for_tableViewer_1_setModel()

    def on_pushButton_2_clicked(self):

        Inputed:str    = self.ui.lineEdit_2.text()
        Filtering:dict = json.loads(Inputed)
        # ..........................................
        self.JSON_Records = self.DIY_JSON_Records_Filter_Records(self.JSON_Records, Filtering)
        # ..........................................
        self.for_tableViewer_1_setModel()

    def on_pushButton_8_clicked(self):

        Inputed:str = self.ui.lineEdit_5.text()
        # ..........................................
        self.JSON_Records = self.DIY_JSON_Records_Use_Pandas_Query(self.JSON_Records, Inputed)
        # ..........................................
        self.for_tableViewer_1_setModel()

if __name__ == "__main__":

    app = QApplication(sys.argv)

    # 设置应用程序样式
    app.setStyle('Fusion')

    # 创建并显示对话框
    dialog = Dialog_System_Table_Viewer()
    dialog.show()

    sys.exit(app.exec())
